/**
 * Copyright © 2019 dream horse Info. Tech Ltd. All rights reserved.
 *
 * @Package: com.gitee.mybatis.fl.util
 * @author: flying-cattle
 * @date: 2019年4月9日 下午8:15:25
 */
package com.fdy.code.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import cn.hutool.core.util.StrUtil;
import com.alibaba.druid.util.StringUtils;
import com.fdy.code.entity.BasisInfo;
import com.fdy.code.entity.ConfigObj;
import com.fdy.code.entity.PropertyInfo;
import com.fdy.code.entity.TableComment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * <p>说明：链接数据库并获取表信息 </P>
 *
 * @author: fangdayang
 * @create: 2023-10-16 20:27
 **/
public class EntityInfoUtil {

    private static final Logger logger = LogManager.getLogger(EntityInfoUtil.class);

    /**
     * 设置pkgs
     *
     * @param bi
     * @return
     * @throws SQLException
     */
    public static BasisInfo getInfo(BasisInfo bi) throws SQLException {
        List<PropertyInfo> columns = new ArrayList<PropertyInfo>();
        ConfigObj configObj = bi.getConfigObj();
        // 创建连接
        Connection con = null;
        PreparedStatement pstemt = null;
        ResultSet rs = null;
        //sql
        String sql = "select column_name,data_type,column_comment from information_schema.columns where table_schema='" +
                configObj.getDatabase() + "' and table_name='" + bi.getTable() + "'";
        logger.info("查询表信息sql【{}】", sql);
        try {
            con = DriverManager.getConnection(configObj.getDbUrl(), configObj.getDbName(), configObj.getDbPassword());
            pstemt = con.prepareStatement(sql);
            rs = pstemt.executeQuery();
            while (rs.next()) {
                String column = rs.getString(1);
                String jdbcType = rs.getString(2);
                String comment = rs.getString(3);
                PropertyInfo ci = new PropertyInfo();
                ci.setColumn(column);
                if (jdbcType.equalsIgnoreCase("int")) {
                    ci.setJdbcType("Integer");
                } else {
                    ci.setJdbcType(jdbcType);
                }
                ci.setComment(comment);
                ci.setProperty(MySqlToJavaUtil.changeToJavaFiled(column));
                ci.setJavaType(MySqlToJavaUtil.jdbcTypeToJavaType(jdbcType));
                //设置注解类型
                if (column.equalsIgnoreCase("id")) {
                    bi.setIdType(ci.getJavaType());
                    bi.setIdJdbcType(ci.getJdbcType());
                }
                columns.add(ci);
                //添加包路径
                Set<String> pkgs = bi.getPkgs();
                pkgs.add(MySqlToJavaUtil.jdbcTypeToJavaTypePck(jdbcType));
                bi.setPkgs(pkgs);
            }
            bi.setCis(columns);

            // 完成后关闭
            rs.close();
            pstemt.close();
            con.close();
            if (null == columns || columns.size() == 0) {
                throw new RuntimeException("未能读取到表或表中的字段。请检查链接url，数据库账户，数据库密码，查询的数据名、是否正确。");
            }
            return bi;
        } catch (Exception e) {
            logger.error("自动生成实体类错误", e);
            throw new RuntimeException("自动生成实体类错误：" + e.getMessage());
        } finally {
            try {
                if (rs != null) rs.close();
            } catch (SQLException se2) {

            }
            // 关闭资源
            try {
                if (pstemt != null) pstemt.close();
            } catch (SQLException se2) {

            }// 什么都不做
            try {
                if (con != null) con.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }

    /**
     * 查询数据库的表
     *
     * @param bi
     * @param sql
     * @return
     */
    public static List<TableComment> getTable(ConfigObj bi, String sql) {
        ArrayList<TableComment> list = new ArrayList<>();
        // 创建连接
        Connection con = null;
        PreparedStatement pstemt = null;
        ResultSet rs = null;
        if (StringUtils.isEmpty(sql)) {
            sql = "SELECT table_name,table_comment FROM information_schema.tables WHERE table_schema='" + bi.getDatabase() + "' AND table_type='base table'";
            logger.info("查询表信息sql【{}】", sql);
        }
        try {
            con = DriverManager.getConnection(bi.getDbUrl(), bi.getDbName(), bi.getDbPassword());
            pstemt = con.prepareStatement(sql);
            rs = pstemt.executeQuery();
            while (rs.next()) {

                String tableCode = rs.getString(1);
                String tableRemark = rs.getString(2);
                list.add(new TableComment(tableCode, tableRemark));
            }
            // 完成后关闭
            rs.close();
            pstemt.close();
            con.close();
            return filterTablelist(list, bi.getCustomTableName());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("查询所有表名异常：" + e.getMessage());
        } finally {
            try {
                if (rs != null) rs.close();
            } catch (SQLException se2) {
            }
            // 关闭资源
            try {
                if (pstemt != null) pstemt.close();
            } catch (SQLException se2) {
            }// 什么都不做
            try {
                if (con != null) con.close();
            } catch (SQLException se) {
                se.printStackTrace();

            }

        }
    }

    /**
     * 过滤全部的数据
     *
     * @param list
     * @param customTableName
     * @return
     */
    private static List<TableComment> filterTablelist(ArrayList<TableComment> list, String customTableName) {
        if (StrUtil.isEmpty(customTableName)) {
            return list;
        }
        String[] split = customTableName.split(StrUtil.COMMA);
        return list.stream().filter(x -> Arrays.asList(split).contains(x.getTableCode())).collect(Collectors.toList());
    }
}
